import { useState, useEffect, useRef } from "react"

export function isFalsy(value: unknown) {
  return value === 0 ? false : !value
}

export function isVoid(value: unknown) {
  return value === undefined || value === null || value === ''
}

// 在一个函数里，改变传入的对象本身是不好的
export function cleanObject(object: {[key: string]: unknown}) {
  const result = { ...object }
  Object.keys(result).forEach(key => {
    const value = result[key]
    if (isVoid(value)) {
      delete result[key]
    }
  })
  return result
}

export function useMount(callback: () => void) {
  useEffect(() => {
    callback()
    // 依赖项里加上callback会造成无限循环，这个和useCallback以及useMemo有关系
  }, [])
}

export function useDebounce<V>(value: V, delay?: number) {
  const [debouncedValue, setDebouncedValue] = useState(value)

  useEffect(() => {
    // 每次在value变化以后，设置一个定时器
    const timeout = setTimeout(() => setDebouncedValue(value), delay)
    // 每次在上一个useEffect处理完以后在运行
    return () => clearTimeout(timeout)
  }, [value, delay])

  return debouncedValue
}

export function useArray<T>(initialArray: T[]) {
  const [value, setValue] = useState(initialArray)

  function clear() {
    setValue([])
  }

  function removeIndex(index: number) {
    const copy = [...value]
    copy.splice(index, 1)
    setValue(copy)
  }

  function add(item: T) {
    setValue([...value, item])
  }

  return { value, setValue, clear, removeIndex, add }
}

export function useDocumentTitle(title: string, keepOnUnmont: boolean = true) {
  const oldTitle = useRef(document.title).current
  // 页面加载时旧title 'React App'
  // 加载后新title

  useEffect(() => {
    document.title = title
  }, [title])

  useEffect(() => {
    return () => {
      if (!keepOnUnmont) {
        // 如果不指定依赖，读到的就是旧title
        document.title = oldTitle
      }
    }
  }, [keepOnUnmont, oldTitle])
}

export function resetRoute() {
  window.location.href = window.location.origin
}

/**
 * 用来返回组件的挂载状态，如果还没挂载或者已经卸载，返回false；反之返回true
 */
export function useMountedRef() {
  const mountedRef = useRef(false)

  useEffect(() => {
    mountedRef.current = true
    return () => {
      mountedRef.current = false
    }
  })
  
  return mountedRef
}

